package cs6238.server;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.UUID;

import cs6238.common.ByteArray;
import cs6238.common.Configuration;

public class FileManager {
	
	/**
	 * Store file and encrypt if it does not exist
	 * @param fileContents
	 * @param clientFilename
	 * @param clientHostname
	 * @param table
	 * @return
	 * @throws Exception
	 */
	public static FileEntry putFile(byte[] fileContents, String clientFilename, String clientHostname, FileAndDelegateEntryTable table) throws Exception{
		
		byte[] hash = FileEncryptor.createHash(fileContents);
		byte[] encryptedHash = FileEncryptor.encryptHash(hash);
		
		String encryptedHashStr = ByteArray.toHexString(encryptedHash);
		
		UUID fileId = table.getFileId(encryptedHashStr);
		
		if(fileId == null){
			//write file to disk and encrypt
			fileId = UUID.randomUUID();
			storeFile(fileContents, hash, fileId);
		}
		
		FileEntry result = new FileEntry(clientHostname, fileId, encryptedHashStr, clientFilename);
		table.addFileEntry(result);
		return result;
	}
	
	private static void storeFile(byte[] fileContents, byte[] hash, UUID fileId) throws Exception{
		String filePath = getFilePath(fileId);
		FileOutputStream output = new FileOutputStream(filePath);
		byte[] encryptedFileContents = FileEncryptor.encrypt(fileContents, hash);
		output.write(encryptedFileContents);
		output.close();
	}
	
	/**
	 * Read encrypted file and decrypt
	 * @param entry
	 * @return
	 * @throws Exception
	 */
	public static byte[] getFile(FileEntry entry) throws Exception{
		String encryptedFileHashString = entry.getEncryptedFileHash();
		byte[] encryptedFileHash = ByteArray.fromHexString(encryptedFileHashString);
		
		byte[] fileHash = FileEncryptor.decryptHash(encryptedFileHash);
		
		String filePath = getFilePath(entry.getFileId());
		File file = new File(filePath);
		long length = file.length();
		byte[] encryptedFileContents = new byte[(int)length];
		FileInputStream input = new FileInputStream(file);
		input.read(encryptedFileContents);
		
		return FileEncryptor.decrypt(encryptedFileContents, fileHash);
	}
	
	/**
	 * Helper function to get the filepath given a fileId
	 * @param fileId
	 * @return
	 */
	protected static String getFilePath(UUID fileId){
		Configuration serverConfig = Configuration.loadServerSettings();
		String folder = serverConfig.getSetting(Configuration.CLIENT_FILE_FOLDER_PATH);
	
		return folder + File.separator + fileId.toString();
	}

	public static void deleteAllFiles() {
		Configuration serverConfig = Configuration.loadServerSettings();
		String folder = serverConfig.getSetting(Configuration.CLIENT_FILE_FOLDER_PATH);
		
		File folderFile = new File(folder);
		if(!folderFile.exists()){
			return;
		}
		
		String[] files = folderFile.list();
		
		for(String filename : files){
			if(!filename.startsWith(".")){
				new File(filename).delete();
			}
		}
	}

}
